package com.yuanxiao.common.core.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  Created by luozongsheng on 14/12/14.
 *  通过反射获得实体相关信息
 */
public class Reflect {

	/**
	 * 获得属性 RColumn注解 value 值
	 * @return
	 * @throws Exception
	 */
	public static String getFieldAnnotationValue(Field f){
		String str = "";
		try{
			str = f.getAnnotation(RColumn.class).value();
		}catch (Exception e){
			e.printStackTrace ();
		}
		return str;
	}

	/**
	 * 获得属性 RColumn注解 isCanBlank 值
	 * @return
	 * @throws Exception
	 */
	public static boolean getFieldIsCanBlankValue(Field f){
		try{
			return f.getAnnotation(RColumn.class).isCanBlank ();
		}catch (Exception e){

		}
		return true;
	}

	/**
	 * 获得属性 RColumn注解 isCanBlank 值
	 * @return
	 * @throws Exception
	 */
	public static boolean getFieldIsExcludeValue(Field f){
		try{
			return f.getAnnotation(RColumn.class).isExclude ();
		}catch (Exception e){
			e.printStackTrace ();
		}
		return true;
	}

	/**
	 * 获得属性 RColumn注解 isObject 值
	 * @return
	 * @throws Exception
	 */
	public static boolean getFieldIsObjectValue(Field f){
		try{
			return f.getAnnotation(RColumn.class).isObject ();
		}catch (Exception e){
			e.printStackTrace ();
		}
		return true;
	}

	/**
	 * 获得属性 RColumn注解 isList 值
	 * @return
	 * @throws Exception
	 */
	public static boolean getFieldIsListValue(Field f){
		try{
			return f.getAnnotation(RColumn.class).isList ();
		}catch (Exception e){
			e.printStackTrace ();
		}
		return true;
	}

	/**
	 * 获得属性 RColumn注解 listNodeName 值
	 * @return
	 * @throws Exception
	 */
	public static String getFieldListNodeNameValue(Field f){
		String str = "";
		try{
			str = f.getAnnotation(RColumn.class).listNodeName ();
		}catch (Exception e){
			e.printStackTrace ();
		}
		return str;
	}

	/**
	 * 获得属性 RColumn注解 classType 值
	 * @return
	 * @throws Exception
	 */
	public static <T> T getClassType(Field f){
		return (T) f.getAnnotation(RColumn.class).classType();
	}

	/**
	 * 为实体属性赋值
	 * @param t
	 * @param f
	 * @param value
	 * @param <T>
	 */
	public static <T> void setFieldValue(T t, Field f, Object value){
		try {
			f.setAccessible(true);
			f.set(t, value);
		} catch (Exception e) {
			e.printStackTrace ();
		}
	}

	/**
	 * 获得类的所有属性
	 * @param t 实体
	 * @return Field[]
	 */
	public static <T> Field[] getFieldList(Class<T> t) {
		Field[] fields = t.getDeclaredFields();
		return fields;
	}

	/**
	 * 实体转为Map
	 * @param t
	 * @param <T>
	 * @return
	 * @throws Exception
	 */
	public static  <T> Map<String, Object> been2Map(T t) {
		Map<String, Object> args = new HashMap<>();
		Field[] fields = Reflect.getFieldList (t.getClass ());
		String annotationValue;
		boolean isExclude;
		for (Field field : fields) {
			isExclude = Reflect.getFieldIsExcludeValue (field);
			if(!isExclude){
				annotationValue = Reflect.getFieldAnnotationValue (field);
				args.put (annotationValue, Reflect.getFieldValue(t, field));
			}
		}
		return args;
	}

	/**
	 * 实体转为Map
	 * @param t
	 * @param <T>
	 * @return
	 * @throws Exception
	 */
	public static  <T> Map<String, Object> been2MapExcludeNull(T t) {
		Map<String, Object> args = new HashMap<>();
		Field[] fields = Reflect.getFieldList (t.getClass ());
		String annotationValue;
		boolean isExclude;
		for (Field field : fields) {
			isExclude = Reflect.getFieldIsExcludeValue (field);
			if(!isExclude){
				if(Reflect.getFieldValue(t, field)!=null && !"".equals (Reflect.getFieldValue(t, field).toString ())){
					annotationValue = Reflect.getFieldAnnotationValue (field);
					args.put (annotationValue, Reflect.getFieldValue(t, field));
				}
			}
		}
		return args;
	}

	/**
	 * 获得实体类中不为空的属性
	 * @param t 实体
	 * @return Field[]
	 */
	public static <T> List<Field> getFieldListNotNull(T t)  throws Exception {
		List<Field> list = new ArrayList<>();
		Field[] fields = t.getClass().getDeclaredFields();
		for(int i=0;i<fields.length;i++){
			if(getFieldValue(t.getClass (), fields[i])!=null && !"".equals(getFieldValue(t.getClass (), fields[i]))){
				list.add(fields[i]);
			}
		}
		return list;
	}

	/**
	 * 获得类中某个属性的get方法
	 * @param t 实体
	 * @param f 属性
	 * @return Method
	 * @throws Exception
	 */
	public static <T> Method getGetMethod(Class<T> t, Field f) {
		Method method = null;
		try {
			method = t.getMethod("get" + getMethodName(f.getName()));
		} catch (Exception e) {
			e.printStackTrace ();
		}
		return method;
	}

	/**
	 * 获得类中某个属性的isXX方法
	 * @param t 实体
	 * @param f 属性
	 * @return Method
	 * @throws Exception
	 */
	public static <T> Method getIsMethod(Class<T> t, Field f) throws Exception {
		return (Method) t.getMethod("is" + getMethodName(f.getName()));
	}

	/**
	 * 获得实体对象属性的值
	 * @param t
	 * @param f
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws Exception
	 */
	public static <T> Object getFieldValue(T t, Field f){
		try {
			return (T) Reflect.getGetMethod(t.getClass (), f).invoke(t);
		} catch (Exception e) {
			e.printStackTrace ();
		}
		return null;
	}

	/**
	 * 获得数据类型
	 * @param f
	 * @return
	 * @throws Exception
	 */
	public static String getFieldType(Field f) throws Exception {
		return f.getType().toString();
	}

	/**
	 * 判断字段类型是否是数值型
	 * @param f
	 * @return
	 * @throws Exception
	 */
	public static boolean isNumber(Field f) throws Exception {
		if("int".equals(getFieldType(f))
				|| "class java.lang.Integer".equals(getFieldType(f))
				|| "short".equals(getFieldType(f))
				|| "class java.lang.Short".equals(getFieldType(f))
				|| "byte".equals(getFieldType(f))
				|| "class java.lang.Byte".equals(getFieldType(f))
				|| "long".equals(getFieldType(f))
				|| "class java.lang.Long".equals(getFieldType(f))
				|| "float".equals(getFieldType(f))
				|| "class java.lang.Float".equals(getFieldType(f))
				|| "double".equals(getFieldType(f))
				|| "class java.lang.Double".equals(getFieldType(f))
				){
			return true;
		}
		return false;
	}

	public static String getFieldTypeName(Field f){
		// 如果类型是Short
		if (f.getGenericType().toString().equals("class java.lang.Short")) {
			return "short";
		}
		if (f.getGenericType().toString().equals("short")) {
			return "short";
		}
		// 如果类型是Byte
		if (f.getGenericType().toString().equals("class java.lang.Byte")) {
			return "byte";
		}
		if (f.getGenericType().toString().equals("byte")) {
			return "byte";
		}
		// 如果类型是Integer
		if (f.getGenericType().toString().equals("class java.lang.Integer")) {
			return "int";
		}
		if (f.getGenericType().toString().equals("int")) {
			return "int";
		}
		// 如果类型是Long
		if (f.getGenericType().toString().equals("class java.lang.Long")) {
			return "long";
		}
		if (f.getGenericType().toString().equals("long")) {
			return "long";
		}
		// 如果类型是Float
		if (f.getGenericType().toString().equals("class java.lang.Float")) {
			return "float";
		}
		if (f.getGenericType().toString().equals("float")) {
			return ("float");
		}
		//如果类型是Double
		if (f.getGenericType().toString().equals("class java.lang.Double")) {
			return "double";
		}
		if (f.getGenericType().toString().equals("double")) {
			return "double";
		}
		//如果类型是String 是封装类
		if (f.getGenericType().toString().equals("class java.lang.String")) {
			return "String";
		}
		// 如果类型是Boolean 是封装类
		if (f.getGenericType().toString().equals("class java.lang.Boolean")) {
			return "boolean";
		}
		// 反射找不到getter的具体名
		if (f.getGenericType().toString().equals("boolean")) {
			return "boolean";
		}
		// 如果类型是Date
		if (f.getGenericType().toString().equals("class java.util.Date")) {
			return "Date";
		}

		return "";
	}

	/**
	 * 获得实体中不为空的值及属性名
	 * @param t 实体对象
	 * @return Map<String,Object>
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws Exception
	 */
	public static <T> Map<String,Object> getFieldValueIsNull(T t) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Exception {
		Map<String,Object> map = new HashMap<String, Object>();
		Object tem = "";
		Field[] fileds = Reflect.getFieldList(t.getClass ());
		for(int i=0;i<fileds.length;i++){
			tem = getFieldValue(t.getClass (), fileds[i]);
			if(tem!=null && !"".equals(tem)){
				map.put(fileds[i].getName(), tem);
			}
		}
		return map;
	}


	/**
	 * 把一个字符串的第一个字母大写、效率是最高的
	 * @param fildeName
	 * @return
	 * @throws Exception
	 */
	private static String getMethodName(String fildeName) throws Exception {
		byte[] items = fildeName.getBytes();
		items[0] = (byte) ((char) items[0] - 'a' + 'A');
		return new String(items);
	}
}
